/*
 * @Author: sonss
 * @Date: 2024-09-03 22:03:10
 * @LastEditTime: 2024-09-04 13:56:00
 * @FilePath: /ss-file-antd/src/pages/Assets/Share/index.tsx
 * @Description:  资源分享
 */

import DownZipButton from '@/components/Utils/DownZipButton';
import { ScrollIndex, Verify } from '@/services/assets_share';
import { descSize } from '@/utils/file';
import { FileOutlined, FolderOpenOutlined, ShareAltOutlined } from '@ant-design/icons';
import {
  PageContainer,
  ProCard,
  ProColumns,
  ProForm,
  ProFormInstance,
  ProFormText,
  ProTable,
} from '@ant-design/pro-components';
import { Button, Divider, Empty, message, Space } from 'antd';
import { saveAs } from 'file-saver';
import moment from 'moment';
import { Key, ReactNode, useEffect, useRef, useState } from 'react';
import { CreateModule as ShareCreateModule, SuccessModule as ShareSuccessModule } from './modules';

type AssetsShareSearchFormValue = {
  content?: string;
};

type AssetsShareSearchRow = {
  key?: Key;
  title?: string;
  size?: number;
  type?: string;
  mtime?: number;
  url?: string;
  ext?: string;
};

type DownZipButtonFile = {
  url: string;
  name?: string;
};

const AssetsShareIndexPage: React.FC = () => {
  const form = useRef<ProFormInstance>();
  const [loading, setLoading] = useState<boolean>(false);
  const [scrollId, setScrollId] = useState<string>();
  const [messageApi, contextHolder] = message.useMessage();
  const [dataSource, setDataSource] = useState<AssetsShareSearchRow[]>([]);
  const [selectKeys, setSelectKeys] = useState<Key[]>([]);
  const [sharer, setSharer] = useState<ASSETS.FILE.SearchParams>();
  const [shared, setShared] = useState<ASSETS.SHARE.CreateResponse>();
  const [downFiles, setDownFiles] = useState<DownZipButtonFile[]>([]);

  const handleClear = () => {
    setDataSource([]);
    setSelectKeys([]);
  };

  const handleScrollIndex = () => {
    handleClear();

    if (!scrollId) {
      return;
    }

    setLoading(true);
    const req: ASSETS.SHARE.ScrollIndexRequest = {
      scrollId,
      limit: 100,
    };
    ScrollIndex(req)
      .then((res) => {
        if (res.code !== 0) {
          return;
        }

        const detail = res.data || {};
        const valueList: AssetsShareSearchRow[] = [];
        let valueIdx: number = 0;

        (detail.categoryList || []).forEach((v) => {
          valueIdx++;
          valueList.push({
            key: valueIdx,
            title: v.name,
            type: '文件夹',
            mtime: v.createTime,
          });
        });

        (detail.fileList || []).forEach((v) => {
          valueIdx++;
          valueList.push({
            key: valueIdx,
            title: v.fileName,
            type: '文件',
            size: v.fileSize,
            mtime: v.createTime,
            url: v.fileUrl,
            ext: v.fileExt,
          });
        });
        setDataSource(valueList);
      })
      .finally(() => {
        setLoading(false);
      });
  };

  useEffect(() => {
    handleScrollIndex();
  }, [scrollId]);

  const handleReset = () => {
    setScrollId(undefined);
    setDataSource([]);
  };

  const search = (params: AssetsShareSearchFormValue) => {
    if (!params.content) {
      messageApi.error('请输入分享链接');
      return;
    }

    const content = params.content?.trim();
    const regex = /分享码:\s*([\w-]+)\s+提取码:\s*([a-zA-Z0-9]{4})/;
    if (!regex.test(content)) {
      messageApi.error('分享链接错误');
      return;
    }

    const matched = content.match(regex);
    if (!matched) {
      messageApi.error('分享链接匹配失败');
      return;
    }

    const req: ASSETS.SHARE.VerifyRequest = {
      orderNo: matched[1],
      shapwd: matched[2],
    };
    Verify(req).then((res) => {
      if (res.code !== 0) {
        return;
      }
      setScrollId(res.data?.scrollId);
    });
  };

  const handleDownload = (record: AssetsShareSearchRow) => {
    fetch(record.url!)
      .then((res) => res.blob())
      .then((blob) => {
        saveAs(blob, record.title || `unknown${record.ext ? '.' + record.ext : ''}`);
      })
      .catch((error) => {
        messageApi.error('下载出错：' + error);
      });
  };

  const columns: ProColumns<AssetsShareSearchRow>[] = [
    {
      dataIndex: 'title',
      title: '文件名',
      render: (_, r) => {
        return (
          <>
            {r.type === '文件夹' ? <FolderOpenOutlined /> : <FileOutlined />} <span>{r.title}</span>
          </>
        );
      },
    },
    {
      dataIndex: 'size',
      title: '大小',
      renderText: (_, r) => {
        return descSize(r.size || 0);
      },
      align: 'right',
    },
    {
      dataIndex: 'type',
      title: '类型',
      align: 'center',
    },
    {
      dataIndex: 'mtime',
      title: '创建时间',
      renderText: (_, record) => {
        return record.mtime ? moment(record.mtime * 1000).format('YY/MM/DD HH:mm') : undefined;
      },
      align: 'center',
    },
    {
      title: '选择操作',
      key: 'action',
      valueType: 'option',
      align: 'center',
      render: (_, record) => {
        return (
          <Space>
            <a onClick={() => handleDownload(record)}>下载</a>
          </Space>
        );
      },
    },
  ];

  const handleSelectChange = (keys: Key[], rows: AssetsShareSearchRow[]) => {
    setSelectKeys(keys);
    setDownFiles(
      rows.map((v) => ({
        url: v.url!,
        name: v.title,
      })),
    );
  };

  const handleShare = () => {
    if (selectKeys.length < 1) {
      messageApi.error('请选择文件');
      return;
    }

    setSharer({
      id: selectKeys.map((v) => v as number),
    });
  };

  const handleSharerClose = () => {
    setSharer(undefined);
  };

  const handleSharerSuccess = (data?: ASSETS.SHARE.CreateResponse) => {
    handleSharerClose();
    setShared(data);
  };

  const handleSharedCoese = () => {
    setShared(undefined);
  };

  const handleDownErrr = (err: any) => {
    messageApi.error(err + '' || '未知错误');
  };

  const body: ReactNode = (() => {
    if (!scrollId) {
      return <Empty />;
    }

    return (
      <>
        <ProTable<AssetsShareSearchRow>
          loading={loading}
          // options={false}
          search={false}
          columns={columns}
          dataSource={dataSource}
          scroll={{ x: 'auto', y: 800 }}
          pagination={false}
          rowSelection={{
            preserveSelectedRowKeys: true,
            onChange: handleSelectChange,
            getCheckboxProps: (record) => ({
              disabled: record.url ? false : true,
            }),
          }}
          tableAlertRender={(p) => {
            return (
              <Space size={24}>
                <span>
                  已选 {p.selectedRowKeys.length} 项
                  <a style={{ marginInlineStart: 8 }} onClick={p.onCleanSelected}>
                    取消选择
                  </a>
                </span>
              </Space>
            );
          }}
          tableAlertOptionRender={() => {
            return (
              <Space size={16}>
                <Button title="分享" onClick={handleShare}>
                  <ShareAltOutlined />
                </Button>
                <DownZipButton
                  size="small"
                  title="下载"
                  files={downFiles}
                  onError={handleDownErrr}
                />
              </Space>
            );
          }}
        />
      </>
    );
  })();

  return (
    <>
      <PageContainer title="资源分享">
        <ProCard>
          <ProForm<AssetsShareSearchFormValue>
            formRef={form}
            layout="vertical"
            submitter={{
              searchConfig: {
                submitText: '查询',
              },
            }}
            onFinish={search}
            onReset={handleReset}
          >
            <ProFormText
              label="分享链接"
              name="content"
              width="xl"
              rules={[
                {
                  required: true,
                  message: '请输入分享链接',
                },
                {
                  pattern: /分享码:\s*([\w-]+)\s+提取码:\s*([a-zA-Z0-9]{4})/,
                  message: '分享链接错误',
                },
              ]}
            />
          </ProForm>
        </ProCard>
        <div>
          <Divider />
        </div>
        <ProCard title="查询结果">{body}</ProCard>
      </PageContainer>
      {sharer && (
        <ShareCreateModule
          params={sharer}
          onSuccess={handleSharerSuccess}
          onClose={handleSharerClose}
        />
      )}
      {shared && (
        <ShareSuccessModule record={shared} onOk={handleSharedCoese} onCancel={handleSharedCoese} />
      )}
      {contextHolder}
    </>
  );
};

export default AssetsShareIndexPage;
